package controllers

import (
	"fmt"
	"github.com/beego/beego/v2/adapter/logs"
	"github.com/beego/beego/v2/client/orm"
	beego "github.com/beego/beego/v2/server/web"
	"github.com/gomodule/redigo/redis"
	"github.com/smartwalle/alipay/v3"
	"project/models"
	"strconv"
	"strings"
	"time"
)

type OrderController struct {
	beego.Controller
}

func (this *OrderController) ShowOrder() {
	// 获取数据
	skuids := this.GetStrings("skuid")
	// 校验数据
	if len(skuids) == 0 {
		logs.Info("请求数据错误")
		this.Redirect("/user/cart", 302)
		return
	}
	// 处理数据
	o := orm.NewOrm()
	conn, _ := redis.Dial("tcp", "10.66.56.13:6379", redis.DialPassword("admin"))
	defer conn.Close()
	// 获取用户数据
	var user models.User
	userName := this.GetSession("userName")
	user.Name = userName.(string)
	o.Read(&user, "Name")
	goodsBuffer := make([]map[string]interface{}, len(skuids))

	var totalPrice float64
	totalCount := 0
	for index, skuid := range skuids {
		temp := make(map[string]interface{})
		id, _ := strconv.Atoi(skuid)
		// 查询商品数据
		var goodsSku models.GoodsSKU
		goodsSku.Id = id
		o.Read(&goodsSku)

		temp["goods"] = goodsSku
		// 获取商品数量
		count, _ := redis.Int(conn.Do("hget", "cart_"+strconv.Itoa(user.Id), id))
		temp["count"] = count
		// 计算小计
		amount := goodsSku.Price * float64(count)
		temp["amount"] = amount
		// 计算总金额和总件数
		totalCount += count
		totalPrice += amount
		goodsBuffer[index] = temp

	}

	this.Data["goodsBuffer"] = goodsBuffer

	// 获取地址数据
	var addrs []models.Address
	o.QueryTable("Address").RelatedSel("User").Filter("User__Id", user.Id).All(&addrs)
	this.Data["addrs"] = addrs

	// 传递总金额和总件数
	this.Data["totalPrice"] = totalPrice
	this.Data["totalCount"] = totalCount
	transferPrice := 10
	this.Data["transferPrice"] = transferPrice
	this.Data["realyPrice"] = totalPrice + float64(transferPrice)

	// 传递所有商品的id
	this.Data["skuids"] = skuids
	// 返回试图
	this.TplName = "place_order.html"
}

// AddOrder 添加订单
func (this *OrderController) AddOrder() {

	// 获取数据
	addrid, _ := this.GetInt("addrid")
	payId, _ := this.GetInt("payId")
	skuid := this.GetString("skuids")
	ids := skuid[1 : len(skuid)-1]
	skuids := strings.Split(ids, " ")
	//totalPrice, _ := this.GetInt("totalPrice")
	totalCount, _ := this.GetInt("totalCount")
	transferPrice, _ := this.GetInt("transferPrice")
	realyPrice, _ := this.GetInt("realyPrice")
	resp := make(map[string]interface{})
	defer this.ServeJSON()
	// 校验数据
	if len(skuids) == 0 {
		resp["code"] = 1
		resp["error"] = "数据库连接错误"
		this.Data["json"] = resp
		return
	}
	// 处理数据
	// 向订单表中插入数据
	o := orm.NewOrm()
	to, err := o.Begin()
	if err != nil {
		logs.Info(err)
		return
	}
	userName := this.GetSession("userName")
	var user models.User
	user.Name = userName.(string)
	o.Read(&user, "Name")
	var order models.OrderInfo
	order.OrderId = time.Now().Format("2006010215030405") + strconv.Itoa(user.Id)
	order.User = &user
	order.OrderStatus = 1
	order.PayMethod = payId
	order.TotalCount = totalCount
	order.TotalPrice = realyPrice
	order.TransitPrice = transferPrice
	// 查询地址
	var addr models.Address
	addr.Id = addrid
	o.Read(&addr)
	order.Address = &addr

	// 执行插入操作
	o.Insert(&order)
	// 向订单商品表中插入数据
	conn, err := redis.Dial("tcp", "10.66.56.13:6379", redis.DialPassword("admin"))
	defer conn.Close()
	if err != nil {
		logs.Info("redis连接错误")
		return
	}
	for _, skuid := range skuids {
		id, _ := strconv.Atoi(skuid)

		var goods models.GoodsSKU
		goods.Id = id
		i := 3
		for i > 0 {

			o.Read(&goods)

			var orderGoods models.OrderGoods
			orderGoods.GoodsSKU = &goods
			orderGoods.OrderInfo = &order

			count, _ := redis.Int(conn.Do("hget", "cart_"+strconv.Itoa(user.Id), id))

			if count > goods.Stock {
				resp["code"] = 1
				resp["error"] = "商品库存不足"
				this.Data["json"] = resp
				err = to.Rollback()
				if err != nil {
					logs.Info("roll back transaction failed", err)
				}
				return
			}
			// 保证库存正确,下单的时候便判断库存，更新库存的时候再进行判断
			preCount := goods.Stock
			orderGoods.Count = count

			orderGoods.Price = goods.Price * float64(count)

			_, err = to.Insert(&orderGoods)
			if err != nil {
				logs.Info("execute transaction`s sql fail,rollback", err)
				err = to.Rollback()
				if err != nil {
					logs.Info("roll back transaction failed", err)
				}
			} else {
				// 插入成功后减少库存增加销量
				goods.Stock -= count
				goods.Sales += count
				updateCount, _ := to.QueryTable("GoodsSKU").Filter("Id", goods.Id).Filter("Stock", preCount).Update(orm.Params{"Stock": goods.Stock, "Sales": goods.Sales})
				if updateCount == 0 {
					logs.Info("回滚事务")
					if i > 0 {
						i -= 1
						continue
					}
					resp["code"] = 2
					resp["error"] = "商品库存改变，订单提交失败"
					this.Data["json"] = resp
					err := to.Rollback()
					if err != nil {
						logs.Info(err)
						return
					}
					return
				} else {
					conn.Do("hdel", "cart_"+strconv.Itoa(user.Id))
					break
				}
			}
			if err != nil {
				return
			}
		}
	}
	err = to.Commit()
	if err != nil {
		logs.Error("commit transaction failed", err)
	}
	// 向订单商品表中插入数据
	// 返回数据
	resp["code"] = 5
	resp["error"] = "ok"
	this.Data["json"] = resp

}

// HandlePay TODO:支付宝支付有问题 订单信息无法识别，建议联系卖家，错误码：INVALID_PARAMETER
// HandlePay 处理支付
func (this *OrderController) HandlePay() {
	var appId = "2021000119648630"
	//var aliPublicKey = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvFU6Ycm+7paGfQ4NEGFLxgOswbnATTfxYP+0wYp8dOuVUlXBvyBHQs4uLTlQfhKIzwtBBJjGyLWaqV9YASyELKd7Yqt7ApLfnny5VR3PBZkcyYCnDpW557vi9yu4sEJut+owmHappq5Ym5+ohcr+bp6ckx7uR+q3t0lHNqPf5I0zaLKYc+0gDQuFOtuo6U4s8+4GRy3s+gxiWNJxJvBFdpG8Z1KjWxzuB1zKPW+ygx73uXNvSaoTuLb6Nn8X0HvO6BogyFkkNBbTNQEr9NzsrpRL6PcTFDVpHJ5+USQf9eEcIepL90a6Y4FtcxmmUPO1NPChenxk1HEo9xFBZJo9bQIDAQAB`
	var privateKey = `MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCc7oR5zjaBwGd/ e69trUi7bTDL1EbxTQvKNlgptsM3sJIHv8Zvna3dQCZNcOefecYv+ZM9t7mvP7OP Ac7puH6Ogd+tl7Uf63AXjSponJAy5hzTBTRsXiUDsGHTgw0Er996/SaLCVpZmHw0 BHrJYKEDSGitRqUp2EM1pAgdkj6v0/M6uqMzGql2nzOwZNyWkf/+XJMO3uUWr5cj pQ1VC7WDmd0WR5TCGAG16V9/vo6nKGkJalPJiMMa0/KCZZG3OjquLHBEso4cWsjP /oXIvIcDoKgomrBsc/gJsyIeaPkGoH0iYDKCtj775QVdBsjYorNYth0SjauhJm4I zeaDcNwJAgMBAAECggEAHQwPDEatkx2sao3XvkrFPB/tWMUNbouOw5qEfhAcmTm/ Bd0q2y0J6fp+PHZKARw2oVmmNdXEclotn6o7hMpH7pO+dbCvb12STWGtOFjGXg12 x15ewjI40rJ6oP5QUg5FpMunrzOHfC77ylsL6StQEj38VhpN5u1nH04hzGtt2/hq WM4GbHIlTzrcimnL+WBs/KElNOVmy5NeSgScRXA7f1TnwYYZgtDXaomrEwg/eaxH qp84blwjFhxyhlRmtVtX4BqZtH+PXMTdAcjMehFT5mWMqk46xAnwoaf6XWOkfMkS SVDTOAetch59asRV9Fx5Ew+2gFVNT6JV4pVz36hWCwKBgQC6n6D2oX94FcX4clH8 korZ5KIEb6zXOIC4vDyqgf/gFa33v6SCt2PsGMuucE2d6dwS+lPhHOAuQz0Y8/Jv GBbHDP4tVYDwtKi08iPD46rlvYuIDgE9MX6J8Wbr+6DqiH1/WC2d8sQJSwiB6nx8 dUq9oDtVeyC/TzsTC4YTv5NzcwKBgQDXRTXdLptQagO6k8I6qd/d706oHUnjDHiL ispavZgXUyHYj8HvIJdbcugTMw7BMbZKlJ0vKV7C6BTIuGUp6FYFqJ7NOcTmw/0L Cscy/jfcOPplZsE6tWYW2YLxnVIZb8OEIO6VQwOpwXNJ/KC3bt4pE3knQRKgmc50 DUfbGUnrkwKBgQCLeQ9gIxRT19nrsuyJGbAB5jgbnqaK9mRlK/Ee8Scc/rbUiHpX Yt2frmxSwwWO9h8OY91aSS1WBdRcmLxfwJ4NRy2TDereefX3vVtzY+vt5PmpxeWx KRNL3okv5g++GCHKkUkOWUefNl92UJuWnEYub9jIKswvjfQ1aJBco/l79wKBgEpB 7p24qQzpNRYUSEjSNo4pMbneOJGgyKhiHQGGK0PIgoFgvaZOWMfL8HBHCYztKBO8 BiixnaWgRyMiMItvQNU84GKszdZIvy4i7qoRdZV69i0qb/dfgbLaH0hXW2241vnq HkLQ1h+lwq4//fSowuvqcr1uvg02YTg5KJNUuuIPAoGBALGMWZGZh+u5ncZkH5DE LwfSSdknsy9JI7U5pIv4cb9Xyap8oPQoVKVcH2AUJEnObBk9qdaPHY3T3g/dfNf4 pOkH73ezHsTfBj8a/g/eym/5OMbOE+gY/5CL0ZD3UGK+2mFWGSiLBOu6LL6TKKrh jCsVDZVj/2+hJgx+SD7eAvwd`
	//var privateKey = "xxx" // 必须，上一步中使用 RSA签名验签工具 生成的私钥
	var client, err = alipay.New(appId, privateKey, false)

	//client.LoadAppPublicCertFromFile("appCertPublicKey_2017011104995404.crt") // 加载应用公钥证书
	//client.LoadAliPayRootCertFromFile("alipayRootCert.crt")                   // 加载支付宝根证书
	//client.LoadAliPayPublicCertFromFile("alipayCertPublicKey_RSA2.crt")       // 加载支付宝公钥证书

	// 将 key 的验证调整到初始化阶段
	if err != nil {
		fmt.Println(err)
		return
	}
	// 获取数据
	orderId := this.GetString("orderId")
	totalPrice := this.GetString("totalPrice")

	var p = alipay.TradePagePay{}
	//p.NotifyURL = "http://xxx"
	p.ReturnURL = "https://127.0.0.1:8081/user/payok"
	p.Subject = "天天生鲜"
	p.OutTradeNo = orderId
	p.TotalAmount = totalPrice
	p.ProductCode = "QUICK_MSECURITY_PAY"
	logs.Info(p)
	url, err := client.TradePagePay(p)
	if err != nil {
		fmt.Println(err)
	}

	var payURL = url.String()
	//fmt.Println(payURL)
	this.Redirect(payURL, 302)
	// 这个 payURL 即是用于支付的 URL，可将输出的内容复制，到浏览器中访问该 URL 即可打开支付页面。
}

// PayOk 支付成功
func (this *OrderController) PayOk() {
	// 获取数据
	orderId := this.GetString("out_trade_no")
	// 校验数据
	if orderId == "" {
		logs.Info("支付返回数据错误")
		this.Redirect("/user/userCenterOrder", 302)
		return
	}
	// 操作数据
	o := orm.NewOrm()
	count, _ := o.QueryTable("OrderInfo").Filter("OrderId", orderId).Update(orm.Params{"Orderstatus": 2})
	if count == 0 {
		logs.Info("支付返回数据错误")
		this.Redirect("/user/userCenterOrder", 302)
		return
	}
	// 返回视图
	this.Redirect("/user/userCenterOrder", 302)
}
